/*  This file is part of -_-.

    -_- is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    -_- is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with -_-.  If not, see <http://www.gnu.org/licenses/>.

    Copyright 2012-2013 Oliver Katz */

#ifndef __COMMON_ARGS_H
#define __COMMON_ARGS_H

#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <unistd.h>
#include <stdarg.h>

#include "data.h"

//struct z_arg: a single argument
typedef struct
{
	char *arg; //memberof z_arg: the name of the argument (contains alphanumerics and hyphons i.e. "hello-world" for --hello-world)
	char a; //memberof z_arg: the shorthand name of the argument ('a' for -a)
	char *val; //memberof z_arg: the value of the argument (--hello-world=value)
	int flagged; //memberof z_arg: whether the argument was used on the command line or not

	char *desc; //memberof z_arg: a description of the argument for --help
	char **examples; //memberof z_arg: example values of the argument for --help
} z_arg;

//struct z_arg_buffer: a buffer for arguments
typedef struct
{
	char *name; //memberof z_arg_buffer: the name of the application
	char *version; //memberof z_arg_buffer: the version of the application
	char *author; //memberof z_arg_buffer: the author of the application
	int year; //memberof z_arg_buffer: the year of the current version

	char *usage; //memberof z_arg_buffer: the usage string for the application

	z_arg *buf; //memberof z_arg_buffer: this is where all the arguments are stored
	z_size head; //memberof z_arg_buffer: how many arguments are currently defined
	z_size size; //memberof z_arg_buffer: the allocated size of the buffer in arguments
} z_arg_buffer;

z_arg_buffer z_arg_buffer_init(z_size s, char *u); //methodof z_arg_buffer: initializer
int z_arg_buffer_release(z_arg_buffer ab); //methodof z_arg_buffer: uninitializer
int z_arg_buffer_sign(z_arg_buffer *ab, char *n, char *v, char *a, int y); //methodof z_arg_buffer: sets the signature information of the argument buffer
//argof z_arg_buffer_sign: char *n: the name of the application
//argof z_arg_buffer_sign: char *v: the version of the application
//argof z_arg_buffer_sign: char *a: the author of the application
//argof z_arg_buffer_sign: int y: the year of the current version
int z_arg_buffer_append(z_arg_buffer *ab, char *arg); //methodof z_arg_buffer: append a new argument
//argof z_arg_buffer_append: char *arg: the name of the argument ("hello-world" for --hello-world)
//returnof z_arg_buffer_append: int: 0 on success, 1 on argument buffer overflow
int z_arg_buffer_append_with_shorthand(z_arg_buffer *ab, char *arg, char a); //methodof z_arg_buffer: same as z_arg_buffer_append, but with a shorthand ('a' for -a)
z_size z_arg_buffer_find(z_arg_buffer *ab, char *arg); //methodof z_arg_buffer: finds the index of 'arg' (mostly for internal use)
//returnof z_arg_buffer_find: z_size: returns the allocated size of the buffer in arguments (z_arg_buffer.size) if the argument cannot be found
int z_arg_buffer_describe(z_arg_buffer *ab, char *arg, char *desc); //methodof z_arg_buffer: add description to argument
//returnof z_arg_buffer_describe: int: 0 on success, 1 if the argument cannot be found
int z_arg_buffer_example(z_arg_buffer *ab, char *arg, ...); //methodof z_arg_buffer: adds examples to argument
//returnof z_arg_buffer_example: int: 0 on success, 1 if the argument cannot be found
//argof z_arg_buffer_example: char *arg: the first argument, keep adding char * arguments ending with a NULL for more examples
int z_arg_buffer_flag_get(z_arg_buffer *ab, char *arg); //methodof z_arg_buffer: returns whether the argument has been specified on command line
int z_arg_buffer_flag_set(z_arg_buffer *ab, char *arg, int f); //methodof z_arg_buffer: sets whether the argument has been specified on command line
char *z_arg_buffer_value_get(z_arg_buffer *ab, char *arg); //methodof z_arg_buffer: returns the value of the argument
//returnof z_arg_buffer_value_get: char *: NULL on failure
char *z_arg_buffer_value_set(z_arg_buffer *ab, char *arg, char *v); //methodof z_arg_buffer: sets the value of the argument
//returnof z_arg_buffer_value_set: char *: NULL on failure
int z_arg_buffer_dump(z_arg_buffer *ab); //methodof z_arg_buffer: displays --help screen

int z_init_args(z_arg_buffer *ab, int argc, char *argv[]); //methodof z_arg_buffer: calls init on argument buffer
//returnof z_init_args: int: 1 if the program is requested to halt, 0 otherwise

/// z_arg_buffer is how you parse command line arguments in -_-. For example:
/// {{// let's make an argument buffer with a maximum of 1024 arguments
/// // and a usage string as follows, so when the user passes --help,
/// // it'll look like: usage: test-program [OPTIONS]
/// z_arg_buffer abuf = z_arg_buffer_init(1024, "test-program [OPTIONS]");
/// 
/// // now let's add some signature information
/// z_arg_buffer_sign(&abuf, "test-program", "1.0", "Oliver Katz", 2013);
///
/// // first argument for everything...
/// z_arg_buffer_append_with_shorthand(&abuf, "hello-world", 'a');
/// z_arg_buffer_describe(&abuf, "hello-world", "this is a test argument");
/// z_arg_buffer_value_set(&abuf, "hello-world", "thisIsATestValue");
///
/// // let's run the init function
/// if (z_init_args(&abuf, argc, argv)) // we'll assume we got argc and argv from main
/// _exit(0);
/// printf("%s\n", z_arg_buffer_value_get(&abuf, "hello-world")); // this should print "thisIsATestValue", unless specified otherwise
/// // for example: test-program --hello-world=HI
/// // would print "HI"
/// 
/// // release the buffer
/// z_arg_buffer_release(abuf);}}

#endif
